classdef Innervation_index < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        InnervationIndexUIFigure        matlab.ui.Figure
        cSwagataDeyIndranilRoyLabel     matlab.ui.control.Label
        InnervationIndexEditField       matlab.ui.control.NumericEditField
        InnervationIndexEditFieldLabel  matlab.ui.control.Label
        EditField                       matlab.ui.control.NumericEditField
        CropOptionsDropDown             matlab.ui.control.DropDown
        CropOptionsDropDownLabel        matlab.ui.control.Label
        StepsLabel                      matlab.ui.control.Label
        CutoffAlgortithmDropDown        matlab.ui.control.DropDown
        CutoffValueEditField            matlab.ui.control.NumericEditField
        CutoffValueEditFieldLabel       matlab.ui.control.Label
        CutoffAlgortithmDropDownLabel   matlab.ui.control.Label
        CalculateButton                 matlab.ui.control.Button
        LoadFolderButton                matlab.ui.control.Button
        UIAxes                          matlab.ui.control.UIAxes
    end

    % Callbacks that handle component events
    methods (Access = private)

        % Button pushed function: LoadFolderButton
        function LoadFolderButtonPushed(app, event)
            % Innervation Index v1.0
            % (c) Indranil Roy, Swagata Dey
            % August 13, 2023
            % Weizmann Institute of Science
            % This app loads tiff images from a folder and calculates 
            % innervation index by either otsu or user defined threshold.

            % This app loads tiff images of neuron terminals in footpad 
            % saved in a single folder. It then lets the user crop the 
            % image by either freehand drawing or polygon. 
            % The user can choose a thresholding method, either 
            % binary thresholding or Otsus method and calculates 
            % the Innervation index and saves it as a txt file 
            % in the same folder. 
            % The user can access the intermediate steps 
            % from .MAT file saved in same folder.
            
            fdir='C:\\Users\';

            fdir = uigetdir(fdir, 'Please select the Folder containing all images');
            if fdir==0
                msgbox('Please select a valid folder');
                fdir='C:\\Users\';
            end
            figure(app.InnervationIndexUIFigure);

            assignin('base','fdir', fdir);
            files = [dir(fullfile(fdir, '*.tif'));...
                dir(fullfile(fdir, '*.tiff'))];

            % files = [dir(fullfile(fdir, '*.tif'));...
            %     dir(fullfile(fdir, '*.tiff'));...
            %     dir(fullfile(fdir, '*.jpg'));...
            %     dir(fullfile(fdir, '*.jpeg'));...
            %     dir(fullfile(fdir, '*.png'));...
            %     dir(fullfile(fdir, '*.bmp'))];
            % assignin('base','files', files);
            assignin('base','files', files);
            if isempty(files)
                msgbox('No TIFF file in the selected folder');
            else
                msgbox('TIFF files are detected the selected folder');

                L = length(files);
                images{1,L} = [];
                for i = 1:L
                    images{i} = imread([files(i).folder '\' files(i).name]);
                end
                assignin('base','images', images);
                ax1 = app.UIAxes;
                % im = imadjust(images{1});
                % [imRGB] = cat(3, im, im, im); %convert grayscale image to RGB
                % [imHSV] = rgb2hsv(imRGB);
                % imHSV(:,:,1) = 163./360; %Change the "hue" of the image, norm to 360 degrees
                % imHSV(:,:,2) = 1 - imHSV(:,:,2);
                % res = hsv2rgb(imHSV);
                % imshow(res, 'Parent', ax1);
                imshow(imadjust(images{1}), 'Parent', ax1);
            end

        end

        % Button pushed function: CalculateButton
        function CalculateButtonPushed(app, event)
            files = evalin('base', 'files');
            images = evalin('base','images');
            fileID = fopen([files(1).folder '\' 'innervationIndex.txt'],'a');
            cropType = string(app.CropOptionsDropDown.Value);
            cutAlgo = string(app.CutoffAlgortithmDropDown.Value);
            ax1 = app.UIAxes;
            area(length(images),1) = 0;
            innIndx(1:length(images),1) = 0;
            ones(1:length(images),1) = 0;
            CroppedImages{length(images),1}=[];
            for i=1:length(images)
                app.EditField.Value = i;
                A = images{i};
                imshow(imadjust(A), 'Parent', ax1);
                if cropType == 'Polygon'
                    h = drawpolygon(ax1); %draw something
                elseif cropType == 'Freehand'
                    h = drawfreehand(ax1);
                end
                M = ~h.createMask();
                A(M) = 0;
                s=numel(A);
                zeross=sum(A(:)==0);
                area(i,1)=s-zeross;
                assignin('base','area', area);
                imshow(imadjust(A), 'Parent', ax1);

                answer = questdlg('Do you need fine cropping?', ...
                    'Fine Crop', ...
                    'Yes', 'No', 'Yes');
                switch answer
                    case 'Yes'
                        if cropType == 'Polygon'
                            h = drawpolygon(ax1); %draw something
                        elseif cropType == 'Freehand'
                            h = drawfreehand(ax1);
                        end
                        M = ~h.createMask();
                        A(M) = 0;
                        imshow(imadjust(A), 'Parent', ax1);
                end
                CroppedImages{i,1} = A;                
                if cutAlgo == '1-0 Cut off'
                    threshold_low = app.CutoffValueEditField.Value;
                    threshold_high = 65536;
                    index=A>threshold_low & A<threshold_high;
                    ones(i,1)=sum(index(:)==1);
                    innIndx(i,1) = 100*ones(i,1)/area(i,1);
                elseif cutAlgo == 'Otsu'
                    level = graythresh(A);
                    index = double(imbinarize(rescale(A), level));
                    ones(i,1)=sum(index(:)==1);
                    innIndx(i,1) = 100*(ones(i,1)/area(i,1));
                end
                imshow(index, 'Parent', ax1);
                assignin('base','ones', ones);
                assignin('base','innIndx', innIndx);
                assignin('base','CroppedImages', CroppedImages);
                fprintf(fileID,'%12s \t %6f\n',files(i).name, innIndx(i,1));
                app.InnervationIndexEditField.Value = innIndx(i,1);

                if i == length(images)
                    msgbox('The End!');
                else
                    answer = questdlg('Move on to next?', ...
                        'Next?', ...
                        'Pause (10 seconds)','Next', 'End', 'Next');
                    switch answer
                        case 'Pause (10 seconds)'
                            pause(10);
                        case 'Next'
                            pause(2);
                        case 'End'
                            break
                    end
                end                
            end
            fclose(fileID);
            name_file = [files(1).folder '\workspace.mat'];
            % name_file = 'workspace.mat';
            evalin('base',['save(''' name_file '.mat'');']);
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Get the file path for locating images
            pathToMLAPP = fileparts(mfilename('fullpath'));

            % Create InnervationIndexUIFigure and hide until all components are created
            app.InnervationIndexUIFigure = uifigure('Visible', 'off');
            app.InnervationIndexUIFigure.Color = [0.8235 0.851 0.8471];
            app.InnervationIndexUIFigure.Position = [100 100 676 523];
            app.InnervationIndexUIFigure.Name = 'Innervation Index';
            app.InnervationIndexUIFigure.Icon = fullfile(pathToMLAPP, 'icon.jpg');

            % Create UIAxes
            app.UIAxes = uiaxes(app.InnervationIndexUIFigure);
            xlabel(app.UIAxes, 'X')
            ylabel(app.UIAxes, 'Y')
            zlabel(app.UIAxes, 'Z')
            app.UIAxes.XColor = 'none';
            app.UIAxes.YColor = 'none';
            app.UIAxes.ZColor = 'none';
            app.UIAxes.GridColor = 'none';
            app.UIAxes.Box = 'on';
            app.UIAxes.Position = [165 1 503 523];

            % Create LoadFolderButton
            app.LoadFolderButton = uibutton(app.InnervationIndexUIFigure, 'push');
            app.LoadFolderButton.ButtonPushedFcn = createCallbackFcn(app, @LoadFolderButtonPushed, true);
            app.LoadFolderButton.Position = [28 335 138 38];
            app.LoadFolderButton.Text = 'Load Folder';

            % Create CalculateButton
            app.CalculateButton = uibutton(app.InnervationIndexUIFigure, 'push');
            app.CalculateButton.ButtonPushedFcn = createCallbackFcn(app, @CalculateButtonPushed, true);
            app.CalculateButton.Position = [28 204 138 38];
            app.CalculateButton.Text = 'Calculate';

            % Create CutoffAlgortithmDropDownLabel
            app.CutoffAlgortithmDropDownLabel = uilabel(app.InnervationIndexUIFigure);
            app.CutoffAlgortithmDropDownLabel.HorizontalAlignment = 'right';
            app.CutoffAlgortithmDropDownLabel.Position = [48 481 97 22];
            app.CutoffAlgortithmDropDownLabel.Text = 'Cut off Algortithm';

            % Create CutoffValueEditFieldLabel
            app.CutoffValueEditFieldLabel = uilabel(app.InnervationIndexUIFigure);
            app.CutoffValueEditFieldLabel.HorizontalAlignment = 'right';
            app.CutoffValueEditFieldLabel.Position = [28 399 73 22];
            app.CutoffValueEditFieldLabel.Text = 'Cut off Value';

            % Create CutoffValueEditField
            app.CutoffValueEditField = uieditfield(app.InnervationIndexUIFigure, 'numeric');
            app.CutoffValueEditField.Position = [116 392 50 37];
            app.CutoffValueEditField.Value = 2500;

            % Create CutoffAlgortithmDropDown
            app.CutoffAlgortithmDropDown = uidropdown(app.InnervationIndexUIFigure);
            app.CutoffAlgortithmDropDown.Items = {'1-0 Cut off', 'Otsu'};
            app.CutoffAlgortithmDropDown.Position = [28 451 138 31];
            app.CutoffAlgortithmDropDown.Value = '1-0 Cut off';

            % Create StepsLabel
            app.StepsLabel = uilabel(app.InnervationIndexUIFigure);
            app.StepsLabel.Enable = 'off';
            app.StepsLabel.Position = [11 30 171 162];
            app.StepsLabel.Text = {'Steps:'; '1. Put all your images '; '    (must be TIF) in one folder.'; '2. Set Cut-off algorithm'; '3. Set Cut-off value'; '4. Load the folder containing '; '    your images'; '5. Press calculate'; '6. The innervation indices'; '    are saved in a TXT file in the'; '    same folder.'};

            % Create CropOptionsDropDownLabel
            app.CropOptionsDropDownLabel = uilabel(app.InnervationIndexUIFigure);
            app.CropOptionsDropDownLabel.HorizontalAlignment = 'right';
            app.CropOptionsDropDownLabel.Position = [59 292 76 22];
            app.CropOptionsDropDownLabel.Text = 'Crop Options';

            % Create CropOptionsDropDown
            app.CropOptionsDropDown = uidropdown(app.InnervationIndexUIFigure);
            app.CropOptionsDropDown.Items = {'Polygon', 'Freehand'};
            app.CropOptionsDropDown.Position = [28 262 138 31];
            app.CropOptionsDropDown.Value = 'Polygon';

            % Create EditField
            app.EditField = uieditfield(app.InnervationIndexUIFigure, 'numeric');
            app.EditField.Editable = 'off';
            app.EditField.HorizontalAlignment = 'center';
            app.EditField.FontSize = 14;
            app.EditField.Position = [210 40 27 36];

            % Create InnervationIndexEditFieldLabel
            app.InnervationIndexEditFieldLabel = uilabel(app.InnervationIndexUIFigure);
            app.InnervationIndexEditFieldLabel.HorizontalAlignment = 'right';
            app.InnervationIndexEditFieldLabel.Position = [489 47 97 22];
            app.InnervationIndexEditFieldLabel.Text = 'Innervation Index';

            % Create InnervationIndexEditField
            app.InnervationIndexEditField = uieditfield(app.InnervationIndexUIFigure, 'numeric');
            app.InnervationIndexEditField.Editable = 'off';
            app.InnervationIndexEditField.FontSize = 14;
            app.InnervationIndexEditField.Position = [601 40 38 36];

            % Create cSwagataDeyIndranilRoyLabel
            app.cSwagataDeyIndranilRoyLabel = uilabel(app.InnervationIndexUIFigure);
            app.cSwagataDeyIndranilRoyLabel.FontSize = 10;
            app.cSwagataDeyIndranilRoyLabel.Enable = 'off';
            app.cSwagataDeyIndranilRoyLabel.Position = [521 1 137 22];
            app.cSwagataDeyIndranilRoyLabel.Text = '(c) Swagata Dey, Indranil Roy';

            % Show the figure after all components are created
            app.InnervationIndexUIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = Innervation_index

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.InnervationIndexUIFigure)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.InnervationIndexUIFigure)
        end
    end
end